package com.wangjiang.foundation.mybatis.params;

import lombok.Data;

import java.util.LinkedList;
import java.util.List;

/**
 * 
 *
 * @author wangjiang
 * @date 2021-01-03 03:21:37
 */
@Data
public class Term {

    /**
     * 字段
     */
    private String column;

    /**
     * 值
     */
    private Object value;

    /**
     * 链接类型, 多条件判断
     */
    private Type type = Type.and;

    /**
     * 条件类型
     */
    private TermEnum termType = TermEnum.eq;


    private List<Term> terms = new LinkedList<>();


    public enum Type {
        or, and;

        public static Type fromString(String str) {
            try {
                return Type.valueOf(str.toLowerCase());
            } catch (Exception e) {
                return and;
            }
        }
    }



    public Term or(String term, Object value) {
        return or(term, TermEnum.eq, value);
    }

    public Term and(String term, Object value) {
        return and(term, TermEnum.eq, value);
    }

    public Term or(String term, TermEnum termType, Object value) {
        Term queryTerm = new Term();
        queryTerm.setTermType(termType);
        queryTerm.setColumn(term);
        queryTerm.setValue(value);
        queryTerm.setType(Type.or);
        terms.add(queryTerm);
        return this;
    }

    public Term or(Term orTerm) {
        orTerm.setType(Type.or);
        terms.add(orTerm);
        return this;
    }

    public Term and(String term, TermEnum termType, Object value) {
        Term queryTerm = new Term();
        queryTerm.setTermType(termType);
        queryTerm.setColumn(term);
        queryTerm.setValue(value);
        queryTerm.setType(Type.and);
        terms.add(queryTerm);
        return this;
    }

    public Term and(Term orTerm) {
        orTerm.setType(Type.and);
        terms.add(orTerm);
        return this;
    }

    public Term nest() {
        return nest(null, null);
    }

    public Term orNest() {
        return orNest(null, null);
    }

    public Term nest(String term, Object value) {
        Term queryTerm = new Term();
        queryTerm.setType(Type.and);
        queryTerm.setColumn(term);
        queryTerm.setValue(value);
        terms.add(queryTerm);
        return queryTerm;
    }

    public Term orNest(String term, Object value) {
        Term queryTerm = new Term();
        queryTerm.setType(Type.or);
        queryTerm.setColumn(term);
        queryTerm.setValue(value);
        terms.add(queryTerm);
        return queryTerm;
    }

    public String getColumn() {
        return column;
    }

    public Term setColumn(String column) {
        if (column == null) {
            return this;
        }
        if (column.contains("$")) {
            String tmp[] = column.split("[$]");
            setTermType(TermEnum.parse(tmp[1]));
            column = tmp[0];
        }
        this.column = column;
        return this;
    }

    public Object getValue() {
        return value;
    }

    public Term setValue(Object value) {
        this.value = value;
        return this;
    }

    public Type getType() {
        return type;
    }

    public Term setType(Type type) {
        this.type = type;
        return this;
    }

    public TermEnum getTermType() {
        return termType;
    }

    public Term setTermType(TermEnum termType) {
        this.termType = termType;
        return this;
    }

    public List<Term> getTerms() {
        return terms;
    }

    public Term setTerms(List<Term> terms) {
        this.terms = terms;
        return this;
    }

    public Term addTerm(Term term) {
        terms.add(term);
        return this;
    }

    @Override
    public Term clone() {
        Term term = new Term();
        term.setColumn(column);
        term.setValue(value);
        term.setTermType(termType);
        term.setType(type);
        terms.forEach(t -> term.addTerm(t.clone()));
        return term;
    }

    public static Term build(String column, Object value) {
        return build(column, TermEnum.eq, value);
    }

    public static Term build(String column, TermEnum operator) {
        return build(column, operator, null);
    }

    public static Term build(String column, TermEnum operator, Object value) {
        Term term = new Term();
        term.column = column;
        term.value = value;
        term.termType = operator;
        return term;
    }

}
